#include <iostream>
#include <vector>
#include <string>
#include <unistd.h>
#include <functional>
#include <sys/wait.h>
#include "Task.hpp"
#include "Channel.hpp"

// typedef std::function<void()> wwork_t;
using work_t = std::function<void()>;

enum
{
    OK = 0,
    UsageError,
    PipeError,
    ForkError
};

class ProcessPool
{
public:
    ProcessPool(int n, work_t w) : _processnum(n), _work(w)
    {
    }
    int InitProcessPool()
    {
        // 创建指定个数个子进程
        for (int i = 0; i < _processnum; i++)
        {
            // 创建管道
            int pipefd[2] = {0};
            int n = ::pipe(pipefd);
            if (n < 0)
                return PipeError;

            pid_t id = ::fork();
            if (id < 0)
                return ForkError;

            if (id == 0)
            {
                // 子进程
                // _channels中保存了当前所有管道的写端
                // 子进程只需要将其全部关闭即可
                for (auto &ch : _channels)
                    ch.Close();
                ::dup2(pipefd[0], 0);
                _work();
                exit(1);
            }
            // 父进程
            ::close(pipefd[0]);
            _channels.emplace_back(pipefd[1], id);
            // Channel ch(pipefd[1]);
            // channels.push_back(ch);
        }
        return OK;
    }
    void DispatchTask()
    {
        int who = 0;
        int num = 20;
        while (num--)
        {
            // 选择一个任务，整数
            int task = tm.SelectTask();
            // 选择一个子进程
            Channel &curr = _channels[who++];
            who %= _channels.size();
            // 打印一些日志信息
            std::cout << "***********************************" << std::endl;
            std::cout << "send" << task << "to" << curr.Name() << std::endl;
            std::cout << "***********************************" << std::endl;
            // 派发任务
            curr.Send(task);
        }
    }

    void CleanProcessPool()
    {
        // 版本3
        // for(int i = _processnum - 1;i >= 0;i --)
        // {
        //     _channels[i].Close();
        //     pid_t rid = ::waitpid(_channels[i].Id(), nullptr, 0);
        //     if (rid > 0)
        //     {
        //         std::cout << "child pid: " << rid << "wait ... success" << std::endl;
        //     }
        // }
        // 版本2
        for (auto &ch : _channels)
        {
            ch.Close();
            pid_t rid = ::waitpid(ch.Id(), nullptr, 0);
            if (rid > 0)
            {
                std::cout << "child pid: " << rid << "wait ... success" << std::endl;
            }
        }
        // 版本1
        // for (auto &ch : _channels)
        // {
        //     ch.Close();
        // }
        // for (auto &ch : _channels)
        // {
        //     pid_t rid = ::waitpid(ch.Id(), nullptr, 0);
        //     if (rid > 0)
        //     {
        //         std::cout << "child pid: " << rid << "wait ... success" << std::endl;
        //     }
        // }
    }
    void DebugPrint()
    {
        for (auto e : _channels)
        {
            std::cout << e.Name() << std::endl;
        }
    }

private:
    std::vector<Channel> _channels; // 存储管道对象
    int _processnum;                // 进程池中子进程个数
    work_t _work;
};

void Usage(std::string proc)
{
    std::cout << "Usage: " << proc << "process-sum" << std::endl;
}